
//
// Listing 4: "Chainable" Mock-Objekte
//

#include "interface.h"
#include "consumer.h"

#include <mockpp/ChainableMockObject.h>
#include <mockpp/chaining/ChainingMockObjectSupport.h>

#include <exception>
#include <iostream>

USING_NAMESPACE_MOCKPP


class ChainMock : public Interface
                , public MOCKPP_NS::ChainableMockObject
{
  public:

    ChainMock()
      : MOCKPP_NS::ChainableMockObject(MOCKPP_PCHAR("ChainMock"), 0)
      , MOCKPP_CONSTRUCT_MEMBERS_FOR_VOID_CHAINABLE_EXT1(open, ext)
      , MOCKPP_CONSTRUCT_MEMBERS_FOR_CHAINABLE0(read)
      , MOCKPP_CONSTRUCT_MEMBERS_FOR_VOID_CHAINABLE_EXT1(write, ext)
      , MOCKPP_CONSTRUCT_MEMBERS_FOR_VOID_CHAINABLE0(close)
    {}

    MOCKPP_VOID_CHAINABLE_EXT1(ChainMock, open, const MOCKPP_STD_NS::string &,
                                          ext,  MOCKPP_STD_NS::string);

    MOCKPP_CHAINABLE0(ChainMock, MOCKPP_STD_NS::string, read);

    MOCKPP_VOID_CHAINABLE_EXT1(ChainMock, write, const MOCKPP_STD_NS::string &,
                                          ext,   MOCKPP_STD_NS::string);

    MOCKPP_VOID_CHAINABLE0(ChainMock, close);
};


int main(int argc, char **argv)
{
  try
  {
    ChainMock mock;
    MOCKPP_CHAINER_FOR_EXT(ChainMock, open, ext) open_chainer (&mock);
    MOCKPP_CHAINER_FOR(ChainMock, read) read_chainer (&mock);
    MOCKPP_CHAINER_FOR_EXT(ChainMock, write, ext) write_chainer (&mock);
    MOCKPP_CHAINER_FOR(ChainMock, close) close_chainer (&mock);

    // Erwartungen f�r das Einlesen der Datei
    open_chainer.expects(once())
                .with(eq(MOCKPP_STD_NS::string("datei1.lst")))
                .before(MOCKPP_PCHAR("reader"));

    read_chainer.stubs()
                .will(onConsecutiveCalls(new ReturnStub<MOCKPP_STD_NS::string>("Datenpaket-1"),
                                         new ReturnStub<MOCKPP_STD_NS::string>("Datenpaket-2"),
                                         new ReturnStub<MOCKPP_STD_NS::string>("Datenpaket-3")))
                .id(MOCKPP_PCHAR("reader"));

    close_chainer.expects(once())
                 .after(MOCKPP_PCHAR("reader"));


    // Erwartungen f�r das Zur�ckschreiben der Datei
    open_chainer.expects(once())
                .with(eq(MOCKPP_STD_NS::string("datei1.lst")))
                .before(MOCKPP_PCHAR("writer"));

    write_chainer.expects(once())
                 .with(eq(MOCKPP_STD_NS::string("Datenpaket-1/fertig")));
    write_chainer.expects(once())
                 .with(eq(MOCKPP_STD_NS::string("Datenpaket-2/fertig")));
    write_chainer.expects(once())
                 .with(eq(MOCKPP_STD_NS::string("Datenpaket-3/fertig")))
                 .id(MOCKPP_PCHAR("writer"));

    close_chainer.expects(once())
                 .after(MOCKPP_PCHAR("writer"));


    // Consumer-Klasse ablaufen lassen
    MOCKPP_STD_NS::cout << "Start der Tests" << MOCKPP_STD_NS::endl;

    Consumer consumer(&mock);
    consumer.load();
    consumer.process();
    consumer.save();

    MOCKPP_STD_NS::cout << "Ende der Tests" << MOCKPP_STD_NS::endl;

    // alle restlichen Bedingungen pr�fen
    mock.verify();
    MOCKPP_STD_NS::cout << "Alle Tests wurden fehlerfrei durchlaufen" << MOCKPP_STD_NS::endl;
  }
  catch(MOCKPP_STD_NS::exception &ex)
  {
    MOCKPP_STD_NS::cout << MOCKPP_STD_NS::endl
              << "Fehler aufgetreten.\n" << ex.what() << MOCKPP_STD_NS::endl
              << MOCKPP_STD_NS::endl;
  }
}
